前情提要:昨天把News API的資料都串好了,今天來處理內頁吧!
會有第1點這麼奇怪的處理方式是因為從response可以看出,不是每則新聞都有content,但又想做內頁,所以就把有content的新聞拉出來做內頁,沒有的話就直接導引至原始新聞頁。
第一步我們先在NewsListItem加上content的判斷吧!
articles是儲存在store內的新聞資料,這邊有再新增一個ItemAnchor component處理anchor element,判斷acticles內是否有content,有的話使用react router <Link> component,沒有的話則直接取url開新分頁至原始新聞。
這邊使用Composition(組合)的方式將anchor和news title結合。
可以看到Link to的位置設定在${pathname}/${index}
,因為新聞沒有id,所以就簡單的使用index當作是判斷哪則新聞的依據。
const ItemAnchor = ({ news, pathname, index, children, className }) => {
return news.content ? (
<Link to={`${pathname}/${index}`} className={className}>{children}</Link>
) : (
<a href={news.url} target="_blank" className={className}>
<span className="news-item-anchor-text">{children}</span>
<FontAwesomeIcon icon={faExternalLinkAlt} color="#999" size="xs" />
</a>
);
};
const NewsListItem = ({ articles, pathname }) =>
articles.map((news, index) => (
<li key={index} className="news-item">
<ItemAnchor news={news} pathname={pathname} index={index} className="news-item-anchor">
{news.title}
</ItemAnchor>
</li>
)
);
在處理anchor element這邊我簡單做個區分,如果是連外的新聞Link,有再加個icon示意,所以可以看到下圖慘烈的狀況,幾乎每則新聞都沒有content ಠ_ಠ
接著再回到router.js新增新聞內頁的Route設定,如果news後面有帶參數的話統一使用NewsDetail component顯示內容,而這個URL參數就是index。
const RootRouter = () => {
return (
<Router>
<Layout>
<Switch>
// ...
<Route path="/news/:index" component={NewsDetail} />
// ...
</Switch>
</Layout>
</Router>
);
};
在NewsDetail透過connect取得state資料,之前的使用方法大多只用到第一個參數取state,今天終於可以用到第二個參數取得其它props,透過props可以收到react router的history、location和match等資訊。
要取得URL parameters的話會需要使用match object,match object內的資訊提供<Route path>如何匹配URL,其中包含以下屬性:
實際得到的內容如下:
今天需要借助params的index值取得該筆新聞資料,接著將該筆資料命名為newsDetail作為props傳入component內使用。
因為在新聞內頁要能返回上個history stack,使用了history內的goBack function,而history.goBack()即等於history.go(-1)。順帶一提如果是下一頁的話則使用history.goForward(),這個method也等於執行history.go(1),詳細內容可參閱react-router API history
NewsDatail.js
// ...
const BackButton = ({ goBack }) => (
<span className="back-btn" onClick={goBack}>
<FontAwesomeIcon
icon={faArrowCircleLeft}
color="rgba(0,0,0,.3)"
size="4x"
/>
</span>
);
const NewsDetail = ({ newsDetail, history }) => {
return (
<main className="main news-detail">
<BackButton goBack={history.goBack} />
<NewsDetailContent newsDetail={newsDetail} />
</main>
);
};
const mapStateToProps = ({ news: { articles } }, ownProps) => {
const { index } = ownProps.match.params;
return {
newsDetail: articles[index]
};
};
export default connect(mapStateToProps)(NewsDetail);
以為歷經沒content的新聞已經是失策了,沒想到其實就算有content也不是全文XD
沒關係沒關係小練習而已,大家別介意,透過URL parameters處理的內頁畫面如下
不知不覺變成隨手小練習,真心覺得愧疚,照理來說router的功能應該要可以直接透過Route取得對應的component顯示內容,但因為是透過News API取得資料,所以reload後資料就沒了哈哈哈哈......,這時候大概只能做Redirect返回news,重新取得News資料。
github傳送門
第24天了,覺得很多細節還沒有好好釐清,再繼續好好加油吧!
題外話~
今天我獲得了人生中第一次在台北市區開車的經驗~!
最大的感想是車位真的很難找!